package com.jwd.config

import org.springframework.boot.autoconfigure.web.ErrorController
import org.springframework.stereotype.Controller
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.web.ErrorAttributes
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.http.HttpStatus
import org.springframework.web.context.request.ServletRequestAttributes
import org.springframework.web.context.request.RequestAttributes
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.ResponseBody
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
import org.springframework.web.servlet.ModelAndView
import javax.servlet.ServletRequest
import javax.servlet.ServletRequestWrapper
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletRequestWrapper


/**
 * Created by udi on 2017.3.4.
 */
@RestController
class AppErrorController() : ErrorController {
    companion object {
        const private val ERROR_PATH = "/error"
        private val logger = LoggerFactory.getLogger(AppErrorController::class.java)
        private var appErrorController: AppErrorController? = null
    }

    @Autowired
    private var errorAttributes: ErrorAttributes? = null

    init {
        if (appErrorController == null && errorAttributes != null) {
            appErrorController = AppErrorController(errorAttributes!!)
        }
    }


    constructor(errorAttributes: ErrorAttributes) : this() {
        this.errorAttributes = errorAttributes
    }


    /**
     * Supports the HTML Error View
     * @param request
     * *
     * @return
     */
    @RequestMapping(value = ERROR_PATH, produces = arrayOf("text/html"))
    fun errorHtml(request: HttpServletRequest): ModelAndView {
        return ModelAndView("error", getErrorAttributes(request, false))
    }

    /**
     * Supports other formats like JSON, XML
     * @param request
     * *
     * @return
     */
//    @RequestMapping(value = ERROR_PATH)
//    fun error(request: HttpServletRequest): ResponseEntity<Map<String, Any>> {
//        val body = getErrorAttributes(request, getTraceParameter(request))
//        val status = getStatus(request)
//        return ResponseEntity(body, status)
//    }

    /**
     * Returns the path of the error page.

     * @return the error path
     */
    override fun getErrorPath(): String {
        return ERROR_PATH
    }


    private fun getTraceParameter(request: HttpServletRequest): Boolean {
        val parameter = request.getParameter("trace") ?: return false
        return "false" != parameter.toLowerCase()
    }

    private fun getErrorAttributes(request: HttpServletRequest,
                                   includeStackTrace: Boolean): Map<String, Any> {
        val requestAttributes = ServletRequestAttributes(request)
        val map = this.errorAttributes!!.getErrorAttributes(requestAttributes, includeStackTrace);
        val URL = getOrignalRequestUrl(request); //
        map.put("URL", URL)
        logger.debug("AppErrorController.method [error info]: status-" + map["status"] + ", request url-" + URL)
        return map
    }

    private fun getOrignalRequestUrl(request: ServletRequest): String {
        if (request is ServletRequestWrapper) {
            return getOrignalRequestUrl(request.request);
        }

        if (request is HttpServletRequest) {
            return request.requestURI;
        }
        if (request is org.apache.catalina.servlet4preview.http.HttpServletRequest) {
            return request.requestURI;
        }

        return "";
    }

    private fun getStatus(request: HttpServletRequest): HttpStatus {
        var statusCode = request
                .getAttribute("javax.servlet.error.status_code")
        if (statusCode != null) {
            try {
                return HttpStatus.valueOf(statusCode as Int);
            } catch (ex: Exception) {
            }

        }
        return HttpStatus.INTERNAL_SERVER_ERROR
    }
}



